package com.base.starter.config.shiro;

import org.apache.shiro.mgt.*;
import org.apache.shiro.session.mgt.DefaultSessionManager;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.spring.web.config.DefaultShiroFilterChainDefinition;
import org.apache.shiro.spring.web.config.ShiroFilterChainDefinition;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @author zhou minghao
 * @date 2024/4/23
 * @description
 */
@Configuration
public class ShiroConfig {
    // 配置自定义Realm 配置成权限全路径匹配
    @Bean
    public MyRealm userRealm() {
        MyRealm shiroRealm = new MyRealm();
        //权限全路径匹配
        shiroRealm.setPermissionResolver(new WholePermissionResolver());
        return shiroRealm;
    }

    @Bean
    public ShiroFilterChainDefinition shiroFilterChainDefinition() {
        //通过map定义哪些路径用哪些过滤器，anon表示任何人都能访问，jwt表示需要JWT令牌验证
        Map<String, String> map = new LinkedHashMap<>(5);
        // 获取头像接口
        map.put("/api/avatar/**", "anon");
        // 一些公共接口
        map.put("/api/v1/common/**", "anon");
        //swagger文档地址放行
        map.put("/swagger-ui/**", "anon");
        map.put("/webjars/springfox-swagger-ui/**", "anon");
        map.put("/swagger-resources/**", "anon");
        map.put("/doc.html", "anon");
        map.put("/webjars/**", "anon");
        map.put("/v3/api-docs/**", "anon");

        // 请求进行验证相关接口放行
        map.put("/auth/**", "anon");
        // 用户注册接口放行
        map.put("/api/sys/register/user/register", "anon");
        //自动导入原始数据接口放行
        map.put("/sfds/raw/data/auto/add", "anon");

//        map.put("/**", "anon");

        // jwt拦截器
        map.put("/**", "jwt");
        DefaultShiroFilterChainDefinition chainDefinition = new DefaultShiroFilterChainDefinition();
        chainDefinition.addPathDefinitions(map);
        return chainDefinition;
    }

    @Bean
    public static DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        /**
         * setUsePrefix(false)用于解决一个奇怪的bug。在引入spring aop的情况下。
         * 在@Controller注解的类的方法中加入@RequiresRole等shiro注解，会导致该方法无法映射请求，导致返回404。 加入这项配置能解决这个bug
         */
        defaultAdvisorAutoProxyCreator.setUsePrefix(true);
        //defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
        return defaultAdvisorAutoProxyCreator;
    }

    // 配置security并设置userReaml，避免xxxx required a bean named 'authorizer' that could not be found.的报错
    @Bean
    public SessionsSecurityManager securityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(userRealm());
        //设置关闭Session
        securityManager.setSubjectDAO(subjectDAO());
        securityManager.setSessionManager(sessionManager());

        return securityManager;
    }

    @Bean
    public SubjectDAO subjectDAO() {
        DefaultSubjectDAO defaultSubjectDAO = new DefaultSubjectDAO();
        defaultSubjectDAO.setSessionStorageEvaluator(sessionStorageEvaluator());
        return defaultSubjectDAO;
    }

    /**
     * 关闭session
     *
     * @return
     */
    @Bean
    public SessionManager sessionManager() {
        DefaultSessionManager defaultSessionManager = new DefaultSessionManager();
        defaultSessionManager.setSessionValidationSchedulerEnabled(false);
        return defaultSessionManager;
    }

    /**
     * 关闭session
     *
     * @return
     */
    @Bean
    public SessionStorageEvaluator sessionStorageEvaluator() {
        DefaultSessionStorageEvaluator defaultSessionStorageEvaluator = new DefaultSessionStorageEvaluator();
        defaultSessionStorageEvaluator.setSessionStorageEnabled(false);
        return defaultSessionStorageEvaluator;
    }


}
